package me.kuye.jkuye.core;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import me.kuye.jkuye.aop.Before;
import me.kuye.jkuye.aop.Clear;
import me.kuye.jkuye.aop.Interceptor;

public class ActionInterceptorBuilder {
	public static final Interceptor[] NULL_INTERS = new Interceptor[0];
	private Map<Class<? extends Interceptor>, Interceptor> interceptorMap = new HashMap<Class<? extends Interceptor>, Interceptor>();

	public void addToInterceptorsMap(Interceptor[] globalInters) {
		for (Interceptor interceptor : globalInters) {
			interceptorMap.put(interceptor.getClass(), interceptor);
		}
	}

	public Interceptor[] buildControllerInterceptor(Class<? extends Controller> controllerClass) {
		return createInterceptors(controllerClass.getAnnotation(Before.class));
	}

	Interceptor[] buildMethodInterceptors(Method method) {
		return createInterceptors(method.getAnnotation(Before.class));
	}

	private Interceptor[] createInterceptors(Before beforeAnnotation) {
		if (beforeAnnotation == null) {
			return NULL_INTERS;
		}
		Class<? extends Interceptor>[] interceptorClasses = beforeAnnotation.value();
		if (interceptorClasses.length < 0) {
			return NULL_INTERS;
		}
		Interceptor[] interceptors = new Interceptor[interceptorClasses.length];
		try {
			for (int i = 0; i < interceptors.length; i++) {
				interceptors[i] = interceptorMap.get(interceptorClasses[i]);
				if (interceptors[i] == null) {
					interceptors[i] = interceptorClasses[i].newInstance();
					interceptorMap.put(interceptorClasses[i], interceptors[i]);
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return interceptors;
	}

	public Interceptor[] buildActionInterceptors(Interceptor[] globalInters, Interceptor[] controllerInterceptors,
			Interceptor[] methodInterceptors, Method method) {
		Clear clear = method.getAnnotation(Clear.class);
		if (clear == null) {
			Interceptor[] interceptors = new Interceptor[globalInters.length + controllerInterceptors.length
					+ methodInterceptors.length];
			int index = 0;
			for (int i = 0; i < globalInters.length; i++) {
				interceptors[index++] = globalInters[i];
			}
			for (int i = 0; i < controllerInterceptors.length; i++) {
				interceptors[index++] = controllerInterceptors[i];
			}
			for (int i = 0; i < methodInterceptors.length; i++) {
				interceptors[index++] = methodInterceptors[i];
			}
			return interceptors;
		}
		Class<? extends Interceptor>[] clearInterceptors = clear.value();
		if (clearInterceptors.length == 0) {
			return methodInterceptors;
		}
		Interceptor[] temp = new Interceptor[globalInters.length + controllerInterceptors.length];
		int index = 0;
		for (int i = 0; i < globalInters.length; i++) {
			temp[index++] = globalInters[i];
		}
		for (int i = 0; i < controllerInterceptors.length; i++) {
			temp[index] = controllerInterceptors[i];
		}

		int removeCount = 0;
		for (int i = 0; i < temp.length; i++) {
			for (Class<? extends Interceptor> interClass : clearInterceptors) {
				if (temp[i].getClass().equals(interClass)) {
					temp[i++] = null;
					removeCount++;
					break;
				}
			}
		}
		Interceptor[] result = new Interceptor[temp.length + methodInterceptors.length - removeCount];
		index = 0;
		for (Interceptor interceptor : temp) {
			if (interceptor != null) {
				result[index++] = interceptor;
			}
		}
		for (Interceptor interceptor : methodInterceptors) {
			result[index++] = interceptor;
		}
		return result;
	}
}
